package com.woniu.his.app.service.service.impl;

import java.math.BigDecimal;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.druid.sql.visitor.functions.If;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.his.app.common.AppResultCode;
import com.woniu.his.app.common.enums.AppStatusEnums;
import com.woniu.his.app.infra.mapper.RegistrationMapper;
import com.woniu.his.app.infra.model.Registration;
import com.woniu.his.app.infra.model.RegistrationTimeQuantum;
import com.woniu.his.app.service.service.RegistrationService;
import com.woniu.his.app.service.service.RegistrationTimeQuantumService;
import com.woniu.his.app.service.service.dto.AppDrugItemDto;
import com.woniu.his.app.service.service.dto.AppHistoryRegDto;
import com.woniu.his.app.service.service.dto.RegHistoryDto;
import com.woniu.his.app.service.service.dto.DeptAllDto;
import com.woniu.his.app.service.service.dto.*;
import com.woniu.his.app.service.service.param.PhoneLoginServiceParam;
import com.woniu.his.app.service.service.param.RegistrationServiceParam;
import com.woniu.his.bms.client.BillRecordClient;
import com.woniu.his.bms.client.result.BillRecordResult;
import com.woniu.his.cms.client.NonDrugClient;
import com.woniu.his.cms.client.result.NonDrugItemRecordQuerResult;
import com.woniu.his.dms.client.CaseHistoryClient;
import com.woniu.his.dms.client.result.CaseHistoryResult;
import com.woniu.his.exception.HisException;
import com.woniu.his.mms.client.HerbalPrescriptionClient;
import com.woniu.his.mms.client.MedicineClient;
import com.woniu.his.mms.client.result.HerbalPrescriptionResult;
import com.woniu.his.mms.client.result.MedicineResult;
import com.woniu.his.pms.client.PmsPatientClient;
import com.woniu.his.pms.client.param.PhoneLoginParam;
import com.woniu.his.pms.client.result.PatientLoginResult;
import com.woniu.his.pms.client.result.PatientResult;
import com.woniu.his.result.Result;
import com.woniu.his.sms.client.SmsDeptQueryClient;
import com.woniu.his.sms.client.SmsSkdClient;
import com.woniu.his.sms.client.SmsRegistrationRankClient;
import com.woniu.his.sms.client.SmsStaffClient;
import com.woniu.his.sms.client.result.*;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 挂号表 服务实现类
 * </p>
 *
 * @author dx
 * @since 2022-11-26
 */
@Service
@Slf4j
public class RegistrationServiceImpl extends ServiceImpl<RegistrationMapper, Registration> implements RegistrationService {

    @Resource
    private SmsDeptQueryClient smsDeptQueryClient;

    @Resource
    private SmsStaffClient smsStaffClient;

    @Resource
    private PmsPatientClient pmsPatientClient;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private CaseHistoryClient caseHistoryClient;

    @Resource
    private SmsSkdClient smsSkdClient;

    @Resource
    private RegistrationTimeQuantumService registrationTimeQuantumService;

    @Resource
    private SmsRegistrationRankClient smsRegistrationRankClient;

    @Resource
    private BillRecordClient billRecordClient;

    @Resource
    private NonDrugClient nonDrugClient;

    @Resource
    private MedicineClient medicineClient;

    @Resource
    private HerbalPrescriptionClient herbalPrescriptionClient;

    /**
     * 挂号
     *
     * @param registration 挂号
     */
    @Override
    @GlobalTransactional
    public void registration(RegistrationServiceParam registration) {

        BigDecimal amount = new BigDecimal(0);
        if (registration.getRankId() == 1) {
            amount = amount.add(new BigDecimal(100));
        }
        if (registration.getRankId() == 2) {
            amount = amount.add(new BigDecimal(15));
        }

        //判断
        //根据排班表ID查询科室ID  //2.排班规则是否有效  sms  接口
        Result<SkdResult> skdResult = smsSkdClient.checkSkdIsExist(registration.getSkdId());
        if (!skdResult.isSuccess()) throw new HisException(AppResultCode.USE_EXCEPTION);
//        //1.患者是否存在  pms  接口
//        Result result = pmsPatientClient.checkPatientIsExist(registration.getPatientId());
//        if (!result.isSuccess()) throw new HisException(AppResultCode.SKD_NOT_EXIST);
//
//        //3.科室是否存在  sms  接口
//        Result<DeptResult> dept = smsDeptQueryClient.findDeptById(Math.toIntExact(skdResult.getData().getDeptId()));
//        if (!dept.isSuccess()) throw new HisException(AppResultCode.DEPT_NOT_EXIST);
//        //4.时间段是否存在  本项目 接口
//        RegistrationTimeQuantum time = registrationTimeQuantumService.getById(registration.getTimeQuantumId());
//        if (time == null) throw new HisException(AppResultCode.TIME_NOT_EXIST);

        //挂号
        Registration one = new Registration();
        one.setPatientId(registration.getPatientId());
        one.setCreateTime(new Date());
        one.setEndAttendance(AppStatusEnums.ON.getCode());
        one.setRegistrationStatus(AppStatusEnums.NOT_PAY.getCode());
        one.setSkdId(registration.getSkdId());
        one.setNeedBook(AppStatusEnums.YES.getCode());
        one.setBindStatus(AppStatusEnums.YES.getCode());
        one.setPriority(AppStatusEnums.NO.getCode());
        one.setTimeQuantumId(registration.getTimeQuantumId());
        one.setPatientAgeStr(registration.getPatientAgeStr());
        //根据排班表ID查询科室ID
        one.setDeptId(skdResult.getData().getDeptId());

        //生成订单  bms 接口
        Result<BillRecordResult> billRecord = billRecordClient.createBillRecord(AppStatusEnums.REGISTRATION.getCode(), amount);
        if (!billRecord.isSuccess()) throw new HisException(AppResultCode.USE_EXCEPTION);
        one.setBillId(billRecord.getData().getId());
        save(one);
        //扣库存
        smsSkdClient.deductions(one.getSkdId());
        //生成病历
        caseHistoryClient.createCaseHistoryWhenRegistration(registration.getPatientId(), registration.getSkdId(), one.getId());
    }

    /**
     * 找到所有部门
     *
     * @return {@link List}<{@link DeptAllDto}>
     */
    @Override
    public List<DeptAllDto> findAllDept() {

        //调用sms--》SmsDeptQueryClient接口
        Result<List<DeptResult>> result = smsDeptQueryClient.FindAllDept();
        if (!result.isSuccess()) throw new HisException(AppResultCode.USE_EXCEPTION);
        List<DeptAllDto> list = BeanUtil.copyToList(result.getData(), DeptAllDto.class);
        return list;
    }

    /**
     * 找到所有医生通过部门id
     *
     * @param deptId 部门id
     * @return {@link List}<{@link DeptAllDoctorDto}>
     */
    @Override
    public List<DeptAllDoctorDto> findAllDoctorByDeptId(Integer deptId) {

        //调用sms 接口 入参deptId
        Result<List<StaffInfoResult>> allStaffByDeptId = smsStaffClient.findAllStaffByDeptId(deptId);
        if (!allStaffByDeptId.isSuccess()) throw new HisException(AppResultCode.USE_EXCEPTION);
        List<DeptAllDoctorDto> result = BeanUtil.copyToList(allStaffByDeptId.getData(), DeptAllDoctorDto.class);
        return result;
//        return null;
    }

    /**
     * 手机登录
     *
     * @param loginServiceParam 登录服务参数
     * @return {@link Map}
     */
    @Override
    public Map phoneLogin(PhoneLoginServiceParam loginServiceParam) {
        //调病人信息的接口 pms
        PhoneLoginParam phoneLoginParam = BeanUtil.copyProperties(loginServiceParam, PhoneLoginParam.class);
        Result<PatientLoginResult> patientLoginResultResult = pmsPatientClient.patientPhoneLogin(phoneLoginParam);
        if (!patientLoginResultResult.isSuccess()) throw new HisException(AppResultCode.USE_EXCEPTION);

        Map<String, Object> map = new HashMap<>();
        map.put("userName", patientLoginResultResult.getData().getName());
        map.put("patientId", patientLoginResultResult.getData().getId());
        return map;
    }

    @Override
    public void getCode(String userPhone) {

        String s = stringRedisTemplate.opsForValue().get("patient:login:code:" + userPhone);
        if (s != null) throw new HisException(AppResultCode.CODE_IS_CREATED);

        String str = "";
        Random random = new Random();
        for (int i = 0; i < 6; i++) {
            str += random.nextInt(10);
        }
        System.out.printf(str);
        stringRedisTemplate.opsForValue().setIfAbsent("patient:login:code:" + userPhone, str, 60, TimeUnit.SECONDS);
    }

    @Override
    public List<StaffSkdInfoDto> queryStaffAllSkdByStaffId(Integer staffId) {

        Result<LoginStaffResult> loginStaffById = smsStaffClient.findLoginStaffById(staffId);
        if (!loginStaffById.isSuccess()) throw new HisException(AppResultCode.USE_EXCEPTION);

        //查某员工的所有规则及描述信息 调sms接口

        return null;
    }


    @Override
    public RegHistoryDto queryRegByBillId(Long billId) {
        Registration registration = getOne(new QueryWrapper<Registration>().eq("bill_id", billId));
        if (registration == null) throw new HisException(AppResultCode.REGISTRATION_NOT_EXISTS);
        RegHistoryDto regHistoryDto = BeanUtil.copyProperties(registration, RegHistoryDto.class);
        regHistoryDto.setStatus(registration.getRegistrationStatus());
        return regHistoryDto;

    }

    @Override
    public Boolean paySuccess(Long billId) {
        log.info("ff:{}",billId);
        Registration registration = getOne(new QueryWrapper<Registration>().eq("bill_id", billId));
        registration.setRegistrationStatus("WAIT_DOCTOR");
        updateById(registration);
        return true;
    }

    /**
     * @Description: 根据身份证查询历史挂号信息
     * @Param:
     * @return: dx
     * @Date: 2022/11/26
     */
    @Override
    public List<RegHistoryDto> listAllRegistration(String identificationNo) {

        //根据身份证号获得患者id,需要调用PMS
        PatientResult data = pmsPatientClient.queryPatientByIdentity(identificationNo).getData();
        if (data == null) {
            throw new HisException(AppResultCode.USE_EXCEPTION);
        }
        List<Registration> registrationList = list(new QueryWrapper<Registration>().eq("patient_id", data.getId()));
        //设置挂号医生姓名,挂号级别姓名
        List<RegHistoryDto> regHistoryDtos = BeanUtil.copyToList(registrationList, RegHistoryDto.class);
        for (RegHistoryDto regHistoryDto : regHistoryDtos) {
            Long id = regHistoryDto.getId();
            Long skdId = getById(id).getSkdId();
            //根据排班id获取医生信息  跟新SMS接口即可
            SkdInfoResult skdInfoResult = smsSkdClient.findSkdInfoById(skdId).getData();
            if (skdInfoResult == null) {
                throw new HisException(AppResultCode.USE_EXCEPTION);
            }

            LoginStaffResult staff = smsStaffClient.findLoginStaffById(skdInfoResult.getStaffId().intValue()).getData();
            regHistoryDto.setDoctorName(staff.getStaffName());

            Long registrationRankId = staff.getRegistrationRankId();
            List<RegistrationRankResult> data1 = smsRegistrationRankClient.queryAllRegistrationRank().getData();
            if (data1 == null) {
                throw new HisException(AppResultCode.USE_EXCEPTION);
            }
            regHistoryDto.setRegistrationName(data1.stream().filter(o -> o.getId().equals(registrationRankId)).
                    collect(Collectors.toList()).get(0).getRegistrationRankName());
        }
        return regHistoryDtos;
    }


    /**
     * @Description: 根据病历id查询某次挂号中（检查/拿药）费用（大项 大类）
     * @Param: dx
     * @return:
     * @Date: 2022/11/26
     */
    @Override
    public List<AppHistoryRegDto> listFee(Long caseHistoryId) {
        if (!caseHistoryClient.queryById(caseHistoryId).isSuccess()) {
            //病历不存在
            throw new HisException(AppResultCode.REGISTRATION_NOT_EXISTS);
        }
        List<AppHistoryRegDto> list = new ArrayList<>();
        //挂号费用
        AppHistoryRegDto dto1 = new AppHistoryRegDto();
        RegistrationFeeDto registrationFeeByCase = getRegistrationFeeByCase(caseHistoryId);
        if (registrationFeeByCase != null) {
            dto1.setItemName("挂号");
            dto1.setCurrentNum(1L);
            dto1.setPrice(registrationFeeByCase.getPrice());
            dto1.setStatus(registrationFeeByCase.getRegistrationStatus());
            dto1.setType(registrationFeeByCase.getType());
            dto1.setId(registrationFeeByCase.getId());
            list.add(dto1);
        }
        //检查费用
        List<NonDrugItemRecordQuerResult> data = nonDrugClient.queryResultByCaseId(caseHistoryId).getData();
        if (data != null) {
            for (NonDrugItemRecordQuerResult datum : data) {
                AppHistoryRegDto dto2 = new AppHistoryRegDto();
                dto2.setItemName("检查");
                dto2.setCurrentNum(1L);
                dto2.setPrice(datum.getAmount());
                dto2.setStatus(datum.getNonDrugItemStatus());
                dto2.setType(datum.getType());
                dto2.setId(datum.getId());
                list.add(dto2);
            }
        }
        //拿药费用
        //成药
        MedicineResult medicineResult = medicineClient.listByReg(caseHistoryId).getData().get(0);
        if (medicineResult != null) {
            AppHistoryRegDto dto3 = new AppHistoryRegDto();
            dto3.setItemName("成药");
            dto3.setCurrentNum(1L);
            dto3.setPrice(medicineResult.getAmount());
            dto3.setStatus(medicineResult.getMedicinePrescriptionStatus());
            dto3.setType(medicineResult.getType());
            dto3.setId(medicineResult.getId());
            list.add(dto3);
        }
        //草药
        HerbalPrescriptionResult data1 = herbalPrescriptionClient.queryHerbalPrescriptionByCaseId(caseHistoryId).getData();
        if (data1 != null) {
            AppHistoryRegDto dto4 = new AppHistoryRegDto();
            dto4.setItemName("草药");
            dto4.setCurrentNum(1L);
            dto4.setPrice(data1.getAmount());
            dto4.setStatus(data1.getHerbalPrescriptionStatus());
            dto4.setType(data1.getType());
            dto4.setId(data1.getId());
            list.add(dto4);
        }
        if (list.size() <= 0) throw new HisException(AppResultCode.USE_EXCEPTION);
        return list;
    }

    /**
     * @Description: 查询某次挂号费用（中药 草药（小项） 根据处方id
     * @Param:
     * @return: dx
     * @Date: 2022/11/26
     */
    @Override
    public List<AppDrugItemDto> listFeeDetail(Long prescriptionId, String type) {


        return null;
    }


    /**
     * 获取挂号费用情况
     *
     * @param caseHistoryId
     * @return
     */
    @Override
    public RegistrationFeeDto getRegistrationFeeByCase(Long caseHistoryId) {
        CaseHistoryResult data = caseHistoryClient.queryById(caseHistoryId).getData();
        if (data == null) throw new HisException(AppResultCode.USE_EXCEPTION);
        Registration registration = getById(data.getRegistrationId());
        RegistrationFeeDto registrationFeeDto = BeanUtil.copyProperties(registration, RegistrationFeeDto.class);
        SkdInfoResult data1 = smsSkdClient.findSkdInfoById(registration.getSkdId()).getData();
        if (data1 == null) throw new HisException(AppResultCode.USE_EXCEPTION);
        LoginStaffResult data2 = smsStaffClient.findLoginStaffById(data1.getStaffId().intValue()).getData();
        if (data2 == null) throw new HisException(AppResultCode.USE_EXCEPTION);
        List<RegistrationRankResult> data3 = smsRegistrationRankClient.queryAllRegistrationRank().getData();
        if (data3 == null) throw new HisException(AppResultCode.USE_EXCEPTION);
        for (RegistrationRankResult registrationRankResult : data3) {
            if (registrationRankResult.getId().equals(data2.getRegistrationRankId())) {
                log.info("挂号等级:{}", registrationRankResult);
                registrationFeeDto.setPrice(registrationRankResult.getPrice());
                registrationFeeDto.setType(registrationRankResult.getRegistrationRankName());
                break;
            }
        }
        return registrationFeeDto;
    }


}
